
/**
 * @file main.c
 * @author Morris (morris@mnblog.cn)
 * @brief
 * @version 0.0.1
 * @date 2022-01-17
 *
 * @copyright Copyright (c) 2022
 *
 */
#include "loopbus_hal.h"

#include "acommon_err.h"
#include "alarm_type.h"
#include "bsp.h"
#include "loopbus.h"
#include "bsp_control.h"
#include "app_version.h"


const char debugtime[10]=__TIME__;
const char debugdata[20]=__DATE__;

/*Mr.Wei*/
volatile bus_up_thd_data_t  bus_thd_t={0};	//总线阈值上传存储
volatile Alter_unit_Val   Alter_Val={0};		//修改阈值

#if SHYS_CONFIG_OUTSIDE
volatile bsp_power_dowm_type  bsp_power_lose_t={0};  //24V总线掉电时间结构体
#endif

#define SN_STR                    "%02x:%02x:%02x:%02x:%02x:%02x"
#define SN_VAR(sn)                sn[5], sn[4], sn[3], sn[2], sn[1], sn[0]

#define ONE_HOUR_TO_500MS         (7200U)
#define VCAP_VOLTAGE_SAMPLING_CNT (10U)

#define NEW_POWER_DIR_CHECK
const bk9000_sn_t               *sn                = NULL;
volatile uint8_t                 shortAddress_temp = 0;   /* 临时短地址 */
volatile bk9000_unit_info_t      sys_info          = {0}; /* 设备信息 */
volatile bk9000_unit_operation_t sys_run_info      = {0}; /* 单元运行信息 */
volatile bk9000_unit_event_t     sys_state         = {0}; /* 系统状态 */

/* vcap相关, 判断总线电压 */
volatile uint32_t vcap_voltage_sampling            = 0;   /* vcap电压采样周期 */
volatile int16_t  vcap_voltage                     = 0x0; /* vcap电压 */

volatile uint8_t port_state                        = 0; /* 系统输出端口状态 */

/* 总线连接标志位 */
volatile uint8_t loopbus_connect                   = 0;

/* 指示灯屏蔽, 置1屏蔽, 表示不主动点灯. 默认为脱离总线工作, 指示灯自主控制, 当连接上总线后指示灯由总线控制 */
// volatile uint8_t led_disable                       = 0; /* 指示灯屏蔽, 置1屏蔽, 表示不主动点灯 */

/* 当配置数据改变, 保存eeprom标志. 防止重复写入eeprom, 和优化功耗 */
static volatile uint8_t save_store_flag            = 0;

/* rtc中断函数, 弱定义实现函数, 非必须实现, 不同板子可以定义该函数, 实现500ms rtc中断事件处理 */
__WEAK void rtc_interrupt_handle(void);
/* 任务初始化处理, 弱定义实现函数, 非必须实现, 在进入while(1)前会执行该函数 */
__WEAK void setup(void);
/* 系统复位函数(恢复未编址状态), 弱定义实现函数, 非必须实现, 在收到编址指令会执行该函数 */
__WEAK void sys_reset(void);
/* 报警清除(复位), 弱定义实现函数, 非必须实现, 在收到主机复位指令会执行该函数 */
__WEAK void alarm_clear(void);

__WEAK int leds_pulse(uint16_t t1, uint16_t t2);
__WEAK void leds_ping(uint8_t en);

/* loop函数, 必须实现, 该函数在while(1)中执行, 不要长时间阻塞, 避免其他任务处理不及时和系统复位. */
void loop(void);

void _rtc_interrupt_handle(void)
{
    static uint16_t time_500ms_count = 0;
    time_500ms_count++;
    if (time_500ms_count == ONE_HOUR_TO_500MS) { time_500ms_count = 0; }

    if (vcap_voltage_sampling) vcap_voltage_sampling--;

		bsp_detector_timer_count();//采集计时
	
    rtc_interrupt_handle();
}

int32_t main(void)
{
/*old  do */
//    acommon_err_t ret        = ACOMMON_OK;
//    uint8_t 			reset_flag = 0;

//    save_store_flag          = 0;
//    reset_flag               = bsp_get_reset_flag();

////    bsp_low_power_init();

//    // acommon_log_init();
	
/*new todo 20241211*/
		acommon_err_t ret  = ACOMMON_OK;

    uint8_t reset_flag = 0;

    loopbus_adapter_event_msg_t msg = {0};

    save_store_flag    = 0;
    reset_flag         = bsp_get_reset_flag();	
		
    bsp_clock_init();

    ACOMMON_LOGI("%s %s %s", COMPILE_PROJECT_NAME, COMPILE_VERSION_STRING,
#ifdef NDEBUG
                 "rc"
#else
                 "bs"
#endif
    );
    ACOMMON_LOGI("fw %s build %s", COMPILE_HASH, COMPILE_TIME);
    ACOMMON_LOGI("hw v2.3");
		ACOMMON_LOGI("Softdware v2.0.0");
    ACOMMON_LOGI("HCLK:   %d Hz", Sysctrl_GetHClkFreq());
    ACOMMON_LOGI("PCLK:   %d Hz", Sysctrl_GetPClkFreq());
    ACOMMON_LOGI("RESET:  %02X", reset_flag);

    /* 加载固件长地址 */
    bps_get_loat_number(&sn);

    /* 首次喂狗，本次喂狗后看门狗无法停止 */
    bsp_wdt_feed();

    /* 初始化eeprom, 并从eeprom加载配置, eeprom内阻塞读取， 超时自动由看门狗复位
     */
    eeprom_init();
    ret |= store_event_record_load();
    ret |= store_operation_load((bk9000_unit_operation_t *) &sys_run_info);
    ret |= store_unit_info_get((bk9000_unit_info_t *) &sys_info);
		if(ret != ACOMMON_OK)
		{
			ACOMMON_LOGW("reload config error");
			bsp_reboot();
		}
		
		if (store_sn_check((bk9000_unit_info_t *) &sys_info, (uint8_t *) sn->id) != 0)
    {
		
        /* 校验单元信息错误, 单元恢复初始化 */
        ACOMMON_LOGI("store data ic fault or replace.");
        store_unit_info_get((bk9000_unit_info_t *) &sys_info);
        store_unit_info_reset((bk9000_unit_info_t *) &sys_info);
        bsp_delay_ms(10);
        ret = store_unit_info_get((bk9000_unit_info_t *) &sys_info);
        ACOMMON_LOGI("reload SN[" SN_STR "] Type[0x%02X]", SN_VAR(sys_info.sn), sys_info.type);
    }
    /* 单元配置出错, 停止继续运行. 若开启看门狗, 则等待单元复位 */
    if (ret != ACOMMON_OK)
    {
        ACOMMON_LOGW("reload config error");
        bsp_reboot();
    }

    bsp_wdt_feed();

    shortAddress_temp = sys_info.address;

    ACOMMON_LOGI("SN[" SN_STR "] Type[0x%02X]", SN_VAR(sn->id), sys_info.type);
    for (int i = 0; i < 8; i++)
    {
        ACOMMON_LOGI("ZM[%d] Type[%d] idx[%d]", (i + 1), sys_info.ZM[i].type,
                     sys_info.ZM[i].id);
    }
    ACOMMON_LOGI("Short Address %d, trunk %d, branch %d", sys_info.address,
                 sys_info.trunk, sys_info.branch);

    /* 板级初始化 */
    bsp_init();
#ifdef NEW_POWER_DIR_CHECK
			/* 检测来电方向 */
			power_set_drv_on();
			while (POWER_IN_OFF == power_check_direction()) { bsp_wdt_feed(); }
			dir_drv_off();
#else
			/* 等待24V电源稳定, 可能会比较长时间, 必须喂狗 */
			while (0 == Gpio_GetInputIO(RX_1_PORT, RX_1_PIN)) { bsp_wdt_feed(); }

			ACOMMON_LOGD("loopbus 24v");

			/* 跳过2ms, 规避总线0V信号, 后检测来电方向 */
			bsp_delay_ms(2);
			power_in_direction();
#endif
		
	 /* 注册rtc中断事件, 开始500ms中断处理 */
			bsp_rtc_interrupt_register(_rtc_interrupt_handle);
			bsp_debug_print(SN_STR " boot %02X\n", SN_VAR(sn->id), reset_flag & 0xff);

			/* 如果单元不存在短地址, 进入编址状态 */
			if (sys_info.address != 0 && sys_info.address != 255)
			{
					ACOMMON_LOGI("power on, start");
					bsp_delay_ms(2);
					power_try_peer();
			}
			else
			{
					ACOMMON_LOGI("reset, wait program");
					shortAddress_temp = 0;
					sys_info.address  = 0;
					sys_info.trunk    = 0;
					sys_info.branch   = 0;
				
				#ifdef NEW_POWER_DIR_CHECK
					power_on_in_dir();
				#else
					/* 关闭右端隔离器, 只能从左端开始编址 */
					power_right_off();
					fetl_on();
				#endif
					power_isolation_state_set(POWER_ISOLATION_NORMAL);
					// /* 关闭右端隔离器, 只能从左端开始编址 */
					// power_right_off();
					// fetl_on();
			}
			
    /* 总线初始化 */
    loopbus_hal_init();
	
//    led_alarm_on_delay(30);
		loopbus_led_pulse_register(leds_pulse);
    loopbus_led_ping_register(leds_ping);

    led_alarm_on_delay(10);
			
		 /* 写入单元启动事件 */
    // bk9000_event_record_t recore;
    // recore.event_id = BK9000_EVENT_ID_RST;
    // store_event_record_write(&recore);	

    /* 单元的配置初始化 */
    setup();

/*old  rod  make*/
	bsp_low_power_init();

	/* 上电闪灯30ms， 提示作用 */
		run_led_on();
		delay1ms(15);
		run_led_off();

	/* 低功耗相关配置 */
    bsp_deep_sleep();
	
	/*工作模式初始化*/
	bsp_Work_Modle_Change(0,0,0,1);
	
	/*放大倍数数据读取*/
	bsp_Temp_Parameter_Config();
	#ifdef EVENT_MODLE
	bsp_event_init();
	#endif
	/*继电器复位*/
	relay.reset=1;
	relay.fault_reset_count=0;
	relay.alarm_reset_count=0;
	relay.alarm_start=1;
	relay.fault_start=1;
	
	
	/*硬件校准*/
	#define TEMP_CALIBRETION_MODLE_25 OFF
	#if TEMP_CALIBRETION_MODLE_25
	bsp_PT100_Calibration_Temp_25(26.20);
	#endif   

	
	/*模式切换*/
	#ifdef JTW_HD_BK500_427
	printf("\nJTW-HD-BK500-427\n");
	#elif	JTW_HD_BK500
	printf("\nJTW-HD-BK500\n");
	#elif  JTW_HD_BK500_L
	printf("\nJTW-HD-BK500-L MODLE\n");
	#elif JTW_HD_BK500_E
	printf("\nJTW-HD-BK500-E MODLE\n")
	#else
	printf("\nNULL MODLE\n");
	#endif	
	/*差定温模式*/
	#ifdef TEMP_R
	printf("TEMP R MODLE\n");
	#endif
	#ifdef CHEEK_MODLE
	printf("CHEEK_MODLE\n");
	#endif
	/*事件记录功能*/
	#ifdef EVENT_MODLE
	printf("EVENT_MODLE\n");	
	#endif 
	#ifdef LCCS_MODLE
	printf("LOW_CONSTANT_CURRENT_SOURCE_MODLE\n\n");	
	#endif
  while (1)
   {
       /* 进入低功耗 */
        bsp_deep_sleep();
        /* 低功耗唤醒, 马上喂狗 */
        bsp_wdt_feed();
        bsp_debug_print(SN_STR " look[%d] %02X\n", SN_VAR(sn->id), M0P_WDT->CON_f.R, reset_flag & 0xff);

        /* 总线事件处理, 下发事件, (编址, 复位等) */
        switch (loopbus_get_new_cmd_event(&msg))
        {
            case LOOPBUS_ADAPTER_EVENT_CLR_STATE: /* 复位, 清除状态事件 */
            {
                ACOMMON_LOGD("CLR ALARM");
								//bsp_detector_state_reset();//状态清零
                // if (sys_info.address != 0 && sys_info.address != 255) 
								// { 
								// 	power_try_peer();
								// }
                alarm_clear();
							
								bsp_flag_reset();	/*单元状态以及标志位初始化*/
                loopbus_led_tick_update();
                break;
            }
            case LOOPBUS_ADAPTER_EVENT_RESET: /* 重新编址 */
            {
                store_unit_info_memset_default((bk9000_unit_info_t *) &sys_info);

                shortAddress_temp = 0;
						#ifdef NEW_POWER_DIR_CHECK
                power_on_in_dir();
						#else
                power_right_off();
                fetl_on();
						#endif
                // power_right_off();
                // fetl_on();
                ACOMMON_LOGD("RESET.");

                save_store_flag = 1;

                sys_reset();
							
							  #ifdef LCCS_MODLE
									#define MODLE_INIT OFF
								#else
									#define MODLE_INIT ON
								#endif
											
								#if MODLE_INIT
									/*根据不同单元，初始化不同的模式*/ 
									#ifdef JTW_HD_BK500_427
										/*默认DS类*/
										bsp_Work_Modle_Change(TEMP_MODLE_DS,0,0,0);
									#elif	JTW_HD_BK500
										/*默认A2S类*/
										bsp_Work_Modle_Change(TEMP_MODLE_A2S,0,0,0);
									#elif JTW_HD_BK500_L
										/*默认DS类*/
										bsp_Work_Modle_Change(TEMP_MODLE_DS,0,0,0);
									#elif JTW_HD_BK500_E
										/*默认DS类*/
										bsp_Work_Modle_Change(TEMP_MODLE_DS,0,0,0);
									#endif
								#endif
                break;
            }
            case LOOPBUS_ADAPTER_EVENT_SET_SA:
            {
                loopbus_led_tick_update();
                save_store_flag = 1;
                break;
            }
            default: break;
        }

				if (save_store_flag && (store_unit_info_save(sys_info) == ACOMMON_OK))
        {
            save_store_flag = 0;
						detector_state.syn=1;
            ACOMMON_LOGD("Set shortAddress %d, trunk %d, branch %d", sys_info.address, sys_info.trunk, sys_info.branch);
        }
				/*修改阈值处理*/
				if(Alter_Val.Revise_flag==1)
				{
					 printf("m:%x,d1:%d d2:%d\n",Alter_Val.Smoke_Tsd_Val,Alter_Val.Temp_Tsd_Val,Alter_Val.Temp_early_Val);
					/*模式切换*/
					 bsp_Work_Modle_Change(Alter_Val.Smoke_Tsd_Val,Alter_Val.Temp_Tsd_Val,Alter_Val.Temp_early_Val,0);
					 
					/*阈值修改*/
					/*模式切换协议冲突暂不开启阈值修改功能，需控制器修改逻辑20230818*/
//		 		if(Alter_Val.Smoke_Tsd_Val!=TEMP_CALIBRATION_MODLE)
//		 		{
//					printf("\nThreshold Value Change:d1:%d d2:%d\n",Alter_Val.Temp_Tsd_Val,Alter_Val.Temp_early_Val);
//					bsp_Temp_Alarm_Change(Alter_Val.Temp_Tsd_Val,Alter_Val.Temp_early_Val,temp_work_modle);
//		 		}
					Alter_Val.Revise_flag=0;	
				}
      /* 单元处理循环 */
      loop();
			/* 低功耗唤醒, 马上喂狗 */
      bsp_wdt_feed();
    }
}


